package org.tabularium.logging;

import java.io.*;
import java.util.*;
import java.util.zip.GZIPInputStream;
import org.tabularium.gui.ITaskProgress;
import org.tabularium.text.analysis.StringTokenizer;

public class HttpExtendedLogReader {
	class HttpExtendedIterator implements Iterator {
		HttpExtendedLogReader parent;

		HttpExtendedLogEntry entry = null;

		InputStream is = null;

		BufferedReader reader = null;

		String buffer = null;

		HttpExtendedIterator(HttpExtendedLogReader parent, InputStream is,
				BufferedReader reader) {
			this.parent = parent;
			this.is = is;
			this.reader = reader;
		}

		public boolean hasNext() {
			if (reader == null)
				return false;

			if (entry != null)
				return true;
			try {
				entry = parent.nextEntry(reader);
				if (entry == null) {
					this.close(); // early close so we free the InputStream
					reader = null;
					return false;
				}
			} catch (IOException ex) {
				return false;
			}
			return true;
		}

		public Object next() {
			if (reader == null)
				return null;

			HttpExtendedLogEntry e = entry;
			try {
				if (e == null) {
					e = parent.nextEntry(reader);
					if (e == null) {
						this.close(); // early close so we free the
										// InputStream
						reader = null;
					}
				} else {
					entry = null;
				}
			} catch (IOException ex) {
				return null;
			}
			return e;
		}

		public void remove() {
			// TODO Auto-generated method stub
		}

		public void close() {
			try {
				entry = null;
				parent.close(is);
				reader = null;
			} catch (IOException ex) {
			}
		}
	}

	public final static String[] GZIP_EXTENSIONS = { ".GZ", ".TGZ" };

	ITaskProgress taskMonitor = null;

	File fn = null;

	ArrayList readers = new ArrayList();

	String[] fields = null;

	public HttpExtendedLogReader(File fn) throws IOException {
		this.fn = fn;
		readFields();
	}

	protected static boolean checkGzipExtension(File fn) {
		boolean b = false;
		for (int i = 0; i < HttpExtendedLogReader.GZIP_EXTENSIONS.length && !b; i++)
			b = fn.getName().toUpperCase().endsWith(GZIP_EXTENSIONS[i]);
		return b;
	}

	/**
	 * 
	 * @return
	 */
	public Iterator iterator() throws IOException {
		InputStream is;
		if (HttpExtendedLogReader.checkGzipExtension(fn)) {
			is = new GZIPInputStream(new FileInputStream(fn));
		} else {
			is = new FileInputStream(fn);
		}
		BufferedReader reader = new BufferedReader(new InputStreamReader(is));
		Iterator iter = new HttpExtendedIterator(this, is, reader);
		readers.add(iter);
		return iter;
	}

	/**
	 * Close all the InputStream of the opened iterators.
	 */
	public void close() {
		Iterator iter = readers.iterator();
		while (iter.hasNext()) {
			HttpExtendedIterator httpiter = (HttpExtendedIterator) iter.next();
			httpiter.close();
		}
	}

	public void setTaskProgress(ITaskProgress monitor) {
		taskMonitor = monitor;
		taskMonitor.setTaskDone(false);
		taskMonitor.setProgress(0l);
	}

	private void close(InputStream is) throws IOException {
		is.close();
	}

	private String readLine(BufferedReader reader) throws IOException {
		return reader.readLine();
	}

	/**
	 * 
	 * @param reader
	 * @return an HttpExtendedLogEntry object or null if EOF is reached
	 * @throws IOException
	 */
	private HttpExtendedLogEntry nextEntry(BufferedReader reader)
			throws IOException {
		if ((fields == null) || (fields.length == 0))
			return null;

		String line;
		HttpExtendedLogEntry entry = null;
		while ((line = reader.readLine()) != null) {
			if (line.matches("^[ ]*([#].*){1}") == true) // skip comments and
															// blank lines
				continue;

			entry = new HttpExtendedLogEntry();
			String[] tokens = StringTokenizer.elements(line, " \t");
			for (int i = 0; (i < tokens.length) && (i < fields.length); i++) {
				entry.put(fields[i], tokens[i]);
			}
			break;
		}
		return entry;
	}

	private boolean readFields() throws IOException {
		ArrayList list = new ArrayList();
		InputStream is;
		if (HttpExtendedLogReader.checkGzipExtension(fn)) {
			is = new GZIPInputStream(new FileInputStream(fn));
		} else {
			is = new FileInputStream(fn);
		}
		BufferedReader reader = new BufferedReader(new InputStreamReader(is));
		String line;
		while ((line = reader.readLine()) != null) {
			if (line.matches("(?i)^[ ]*[#][ ]*Fields.*")) {
				line = line.replaceFirst("(?i)^[ ]*[#][ ]*Fields[ ]*[:][ ]*",
						"");
				String[] tokens = StringTokenizer.elements(line, " \t");
				for (int i = 0; i < tokens.length; i++) {
					list.add(tokens[i]);
				}
				break;
			}
		}
		is.close();
		fields = (String[]) list.toArray(new String[] {});
		return true;
	}

}
